﻿namespace FFF.Test.Application.Repositories.FW
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Abp.Domain.Repositories;
    using Abp.EntityFrameworkCore;
    using Abp.ObjectMapping;
    using Abp.UI;
    using Ydm.Helper;
    using Ydm.Extensions;
    using Microsoft.EntityFrameworkCore;
    using AutoMapper.QueryableExtensions;
    using FFF.Test.DataAccess.Framework;
    using FFF.Test.Application.Repositories.FW;
    using FFF.Test.Entity.FW;
    using FFF.Test.Entity.FW.Dto;
    using FFF.Test.Entity.FW.View;
    using Ydm.QueryFilter.Core;

    /// <summary>
    /// 用户表仓储
    /// </summary>
    public class FWUserRepository :
        YdmAbpRepositoryBase<FWUserEntity, Guid, FWUserCreateInputDto, FWUserUpdateInputDto, FWUserDto, ViewFWUser, ViewFWUser>,
        IFWUserRepository
    {
        private readonly IObjectMapper _objectMapper;
        private readonly IFWStandardRole2USerRepository _fWStandardRole2USerRepositor;

        /// <summary>
        /// Initializes a new instance of the <see cref="FWUserRepository"/> class.
        /// 仓储构造方法
        /// </summary>
        /// <param name="dbContextProvider">对应数据库的对象</param>
        /// <param name="objectMapper">自动映射对象</param>
        /// <param name="fWStandardRole2USerRepositor">角色用户</param>
        public FWUserRepository(
            IDbContextProvider<MyDbContext> dbContextProvider,
            IObjectMapper objectMapper,
            IFWStandardRole2USerRepository fWStandardRole2USerRepositor
            )
            : base(dbContextProvider, objectMapper)
        {
            this._objectMapper = objectMapper;
            this._fWStandardRole2USerRepositor = fWStandardRole2USerRepositor;
        }

        /// <summary>
        /// 1.009 通过手机号修改密码(于大明)
        /// </summary>
        /// <param name="inDto">通过手机号修改密码输入dto</param>
        /// <returns>通过手机号修改密码输出dto</returns>
        public async Task<UpdatePwdByPhoneOutDto> UpdatePwdByPhoneAsync(UpdatePwdByPhoneInDto inDto)
        {
            var entity = await base.FirstOrDefaultAsync(x => x.UserCode == inDto.Cellphone);
            if (entity == null)
            {
                throw new UserFriendlyException("未找到用户,请先注册");
            }

            entity.UserPassword = YdmEncrypt.Md5(inDto.Password);
            var result = new UpdatePwdByPhoneOutDto();
            return result;
        }

        /// <summary>
        /// 获取用户信息通过用户GUID(于大明,信息平台)
        /// </summary>
        /// <param name="userGUID">用户GUID</param>
        /// <returns>用户登录输出dto</returns>
        public async Task<ViewFWUser> GetUserInfoByGUID(Guid userGUID)
        {
            ViewFWUser viewUser = await this.GetView().Where(x => x.Id == userGUID
            && x.UserIsDisabeld != 1).FirstOrDefaultAsync();
            return viewUser;
        }

        /// <summary>
        /// 1.003 用户登录(于大明)
        /// </summary>
        /// <param name="inDto">用户登录输入dto</param>
        /// <returns>用户登录输出dto</returns>
        public async Task<ViewFWUser> UserLoginAsync(UserLoginInDto inDto)
        {
            // 如果是加密的字符串那么直接对比 如果不是那么就加密后在对比
            var passWord = inDto.Password;
            if (!passWord.EndsWith("=="))
            {
                passWord = YdmEncrypt.Md5(inDto.Password);
            }

            var userEntity = await base.FirstOrDefaultAsync(x =>
            x.UserPassword == passWord
                && x.UserCode == inDto.UserName
                && x.UserIsDisabeld != 1);
            if (userEntity == null)
            {
                return null;
            }

            ViewFWUser viewFWUser = await this.GetView().FirstOrDefaultAsync(x => x.Id == userEntity.Id);
            viewFWUser.Action2Users = await this.GetSummaryView<ViewFWAction2User>().Where(x => x.UserGUID == userEntity.Id).ToListAsync();
            viewFWUser.ModuleGUIDs = viewFWUser.Action2Users.Select(y => y.ModuleGUID ?? Guid.Empty).Distinct().ToList();
            var functionDtos = viewFWUser.Action2Users.Where(x => x.ActionCode == "00").Select(x => new { x.ParentGUID, x.FunctionGUID }).ToList();
            viewFWUser.AplicationGUIDs = await this.GetSummaryView<ViewFWApplication2Module>().AsNoFilter().Where(x => viewFWUser.ModuleGUIDs.Contains(x.ModuleGUID ?? Guid.Empty)).Select(x => x.ApplicationGUID ?? Guid.Empty).Distinct().ToListAsync();
            List<Guid> functionGUIds = new List<Guid>();
            viewFWUser.Action2Users.Where(c => c.ActionCode == "00").ToList()
                 .ForEach(x =>
                 {
                     functionGUIds.Add(x.ParentGUID ?? Guid.Empty);
                     functionGUIds.Add(x.FunctionGUID ?? Guid.Empty);
                 });

            viewFWUser.FunctionGUIDs = functionGUIds.Distinct().ToList();

            // 更新默认选中的系统ID或者是公司ID
            FWUserUpdateInputDto userUpdateInputDto = new FWUserUpdateInputDto()
            {
                Id = viewFWUser.Id
            };

            if (viewFWUser.DefaultApplicationGUID == null && viewFWUser.AplicationGUIDs.Count > 0)
            {
                userUpdateInputDto.DefaultApplicationGUID = viewFWUser.AplicationGUIDs[0];
                viewFWUser.DefaultApplicationGUID = userUpdateInputDto.DefaultApplicationGUID;
            }

            if (viewFWUser.DefaultBuUnitGUID == null && !viewFWUser.BuUnitNewGUIDs.IsNullOrEmpty())
            {
                userUpdateInputDto.DefaultBuUnitGUID = new Guid(viewFWUser.BuUnitNewGUIDs.Split(",")[0]);
                viewFWUser.DefaultBuUnitGUID = userUpdateInputDto.DefaultBuUnitGUID;
            }

            if (userUpdateInputDto.DefaultApplicationGUID != null || userUpdateInputDto.DefaultBuUnitGUID != null)
            {
                await this.UpdateByDtoAsync(userUpdateInputDto);
            }

            return viewFWUser;
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        /// <param name="input">创建用户输入</param>
        /// <returns>用户信息</returns>
        public override async Task<FWUserDto> CreateByDtoAsync(FWUserCreateInputDto input)
        {
            if (base.GetAll().AsNoTracking().Any(x => x.UserCode == input.UserCode))
            {
                throw new UserFriendlyException("已存在该用户名！");
            }

            input.UserPassword = YdmEncrypt.Md5(input.UserPassword);

            // 主账户的租户Id就是自己的用户ID 后续所有产生的数据都会来自于这个租户ID
            if (input.IsMainAccountUser == 1)
            {
                Guid userId = Guid.NewGuid();
                input.Id = userId;
                input.TenantId = userId;
            }

            var dto = await base.CreateByDtoAsync(input);

            if (!input.StandardRoleGUIDs.IsNullOrEmpty())
            {
                List<Guid> roleGUids = input.StandardRoleGUIDs.Split(",").Select(x => new Guid(x)).ToList();
                foreach (var guid in roleGUids)
                {
                    FWStandardRole2USerCreateInputDto inputDto = new FWStandardRole2USerCreateInputDto()
                    {
                        UserGUID = dto.Id,
                        StandardRoleGUID = guid
                    };
                    await this._fWStandardRole2USerRepositor.CreateByDtoAsync(inputDto);
                }
            }

            return dto;
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="input">修改用户输入</param>
        /// <returns>用户信息</returns>
        public override async Task<FWUserDto> UpdateByDtoAsync(FWUserUpdateInputDto input)
        {
            // 说明是修改密码
            if (!input.UserPassword.IsNullOrEmpty())
            {
                string oldPassword = YdmEncrypt.Md5(input.OldPassword);
                bool isExistsUser = await base.GetAll().AsNoTracking().AnyAsync(x => x.Id == input.Id && x.UserPassword == oldPassword);
                if (!isExistsUser)
                {
                    throw new UserFriendlyException("原密码不正确");
                }
                else
                {
                    input.UserPassword = YdmEncrypt.Md5(input.UserPassword);
                }
            }

            // 更新对应角色权限表
            if (!input.StandardRoleGUIDs.IsNullOrEmpty())
            {
                var guids = await this._fWStandardRole2USerRepositor.GetView().Where(x => x.UserGUID == input.Id).Select(x => x.Id).ToListAsync();

                foreach (var guid in guids)
                {
                    await this._fWStandardRole2USerRepositor.DeleteAsync(guid);
                }

                List<Guid> roleGUids = input.StandardRoleGUIDs.Split(",").Select(x => new Guid(x)).ToList();
                foreach (var guid in roleGUids)
                {
                    FWStandardRole2USerCreateInputDto inputDto = new FWStandardRole2USerCreateInputDto()
                    {
                        UserGUID = input.Id,
                        StandardRoleGUID = guid
                    };
                    await this._fWStandardRole2USerRepositor.CreateByDtoAsync(inputDto);
                }
            }

            return await base.UpdateByDtoAsync(input);
        }

    }
}
